# PONG EXAMPLE
from django.http import HttpResponse
from Queue import Queue, Empty
from threading import Thread
from django.shortcuts import render_to_response
import random
import time

class Game(Thread):
    def __init__(self):
        self.players = [False] * 4
        self.ins = [Queue() for i in range(4)]
        self.outs = [Queue() for i in range(4)]
        super(Game, self).__init__()
    
    def run(self):
        positions = [0] * 4
        players = self.players
        ins = self.ins
        outs = self.outs
        
        boardsize = 600
        ballsize = 25
        paddlesize = 200
        
        paddlespeed = 10
        speedx = 0
        speedy = 0
        nextx = 0
        nexty = 0
        ballpos = []
        framecount = 0
        
        def randspeed():
            return random.choice([-5,-3, 3, 5])
            
        def hits_paddle(paddleid, point):
            '''always hit bots'''
            if not players[paddleid]:
                return True
            return positions[paddleid] <= point <= positions[paddleid]+paddlesize
        
        def vertical_hit():
            '''returns speedx, speedy, nextx, nexty after hit'''
            return randspeed() * -(speedx/abs(speedx)), randspeed(), [ballpos[0], ballpos[1]+speedy]
            
        def horizontal_hit():
            '''returns speedx, speedy, nexty, nexty after hit'''
            return randspeed(), randspeed() * -(speedy/abs(speedy)), [ballpos[0]+speedx, ballpos[1]]
            
        def reset():
            return randspeed(), randspeed(), [300,300]
        
        speedy, speedx, ballpos = reset()
        
        while True:
            if framecount % 100000 == 0:
                for i,p in enumerate(players):
                    if p:
                        try:
                            tmp = ins[i].get(block=False)
                            if tmp == '1':
                                if positions[i] + paddlespeed <= boardsize-paddlesize:
                                    positions[i] += paddlespeed
                                else:
                                    positions[i] = boardsize-paddlesize
                            elif tmp == '0':
                                if positions[i] - paddlespeed >= 0:
                                    positions[i] -= paddlespeed
                                else:
                                    positions[i] = 0
                        except Empty, e:
                            pass
                
                nextx = (ballpos[0] + speedx)
                nexty = (ballpos[1] + speedy)
                
                if nextx >= (boardsize-ballsize):
                    speedx, speedy, ballpos = vertical_hit() if hits_paddle(3,nexty) else reset()
                elif nextx <= 0:
                    speedx, speedy, ballpos = vertical_hit() if hits_paddle(2,nexty) else reset()
                elif nexty >= (boardsize-ballsize):
                    speedx, speedy, ballpos = horizontal_hit() if hits_paddle(1,nextx) else reset()
                elif nexty <= 0:
                    speedx, speedy, ballpos = horizontal_hit() if hits_paddle(0,nextx) else reset()
                else:
                    ballpos = [nextx, nexty]
                    
                for i,pos_idx in enumerate([1,1,0,0,]):#each 'bot' paddle uses ballpos[pos_idx] as value
                    if not players[i]:
                        npos = (nexty if pos_idx == 0 else nextx) - paddlesize/2
                        if npos < 0:
                            npos = 0
                        elif npos > boardsize-paddlesize:
                            npos = boardsize-paddlesize
                        positions[i] = npos
                    
                for i,p in enumerate(players):
                    if p:
                        outs[i].put(positions[:] + ballpos[:])
                        
            framecount += 1
            

game = Game()
game.start()

def home(request):
    text = '<br/>'.join('<a href="/play/%s/">Play %s</a>'%(i,i)
                          for i,v in enumerate(game.players) if not v)
    return HttpResponse(text)

def play(request, id):
    id = int(id)
    if game.players[id]:
        return HttpResponse('player in use')
    game.players[id] = True
    return render_to_response('pong4party.html', {'id':id})

def read(request, id):
    outq = game.outs[int(id)]
    def updater(q):
        while True:
            o = q.get()
            yield str(o) if isinstance(o, list) else ''
    return HttpResponse(updater(outq))
    
def write(request, id):
    q = game.ins[int(id)]
    q.put( request.GET['dir'] )
    return HttpResponse("ok")
  
